package com.cls.business.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.cls.business.mapper.ExpertGroupMapper;
import com.cls.business.service.IExpertExcel8ReviewService;
import com.cls.business.strategy.ExpertExcel8ReviewRowStrategy;
import com.cls.business.strategy.NoticeStrategy;
import com.cls.business.vo.review.result.*;
import com.cls.common.enums.DictEnum;
import com.cls.common.enums.TemplatesFileName;
import com.cls.common.utils.FileUtil;
import lombok.RequiredArgsConstructor;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 魏起成
 * 根据review表导出excel的service
 */
@Service
@RequiredArgsConstructor
public class ExpertExcel8ReviewServiceImpl implements IExpertExcel8ReviewService {

    private final ExpertGroupMapper expertGroupMapper;

    @Autowired
    private Map<String, ExpertExcel8ReviewRowStrategy> noticeStrategyMap = new ConcurrentHashMap<>();

    /**
     * 魏起成
     * 导出年度评审结果
     *
     * @param period
     * @param response
     * @param
     */
    @Override
    public void exportReviewResult(String period, HttpServletResponse response, String classType) throws IOException {

        List<ReviewResultExportVO> reviewResultExportVOS = this.expertGroupMapper.selectAllTopicAndExpertByPeriod(period, classType);
        //获取注入的自定义写入申请课题行
        ExpertExcel8ReviewRowStrategy reviewExportExcelImpl = noticeStrategyMap.get("reviewExportExcelImpl");
        //定义标题
        List<String> titles = CollUtil.newArrayList("编号", "申报课题名称", "申请人", "单位及职务职称", "专家评分", "总分", "补充意见");
        ExcelWriter excelWriter = this.writeExpertGroup(null, reviewResultExportVOS, titles, 4, reviewExportExcelImpl);
//        File file = new File("D:\\360Downloads\\" + System.currentTimeMillis() + TemplatesFileName.REVIEW_RESULT_CON.getFileName());
//        file.createNewFile();
       /* FileOutputStream fileOutputStream = new FileOutputStream(fReviewResultExportVOile);
        excelWriter.flush(fileOutputStream, true);
        //此处记得关闭输出Servlet流
        IoUtil.close(fileOutputStream);*/
        //可以自适应宽度
//        excelWriter.autoSizeColumnAll();
        String fileName = String.format(TemplatesFileName.REVIEW_RESULT_CON.getFileName(), period);
        FileUtil.downloadExcel(excelWriter, fileName, response);
    }

    /**
     * 魏起成
     * 导出结项验收课题成果鉴定结果统计表
     *
     * @param period
     * @param response
     * @param
     */
    @Override
    public void exportItemResult(String period, HttpServletResponse response, String typeCode) throws IOException {

        List<ReviewResultExportVO> reviewResultExportVOS = this.expertGroupMapper.selectAllTopicAndExpertByPeriod(period, typeCode);
        //获取注入的自定义写入申请课题行
        ExpertExcel8ReviewRowStrategy reviewExportExcelImpl = noticeStrategyMap.get("itemExportExcelImpl");
        //定义标题
        List<String> titles = CollUtil.newArrayList("排序", "立项编号", "课题名称", "主持人", "单位及职称", "鉴定专家及分数", "总分", "建议等级", "备注");
        String title = period + "期结项验收课题成果鉴定结果统计表";
        ExcelWriter excelWriter = this.writeExpertGroup(title, reviewResultExportVOS, titles, 5, reviewExportExcelImpl);
        /*File file = new File("D:\\360Downloads\\" + System.currentTimeMillis() + TemplatesFileName.REVIEW_RESULT_CON.getFileName());
        file.createNewFile();
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        excelWriter.flush(fileOutputStream, true);
        //此处记得关闭输出Servlet流
        IoUtil.close(fileOutputStream);*/
        //可以自适应宽度
//        excelWriter.autoSizeColumnAll();
        String fileName = String.format(TemplatesFileName.REVIEW_RESULT_CON.getFileName(), period);
        FileUtil.downloadExcel(excelWriter, fileName, response);
    }


    /**
     * 设置统一的excel样式
     *
     * @param excelWriter
     */
    private void setExcelStyle(ExcelWriter excelWriter) {
        //头部字体
        Font headFont = excelWriter.createFont();
        headFont.setBold(true);
        headFont.setFontName("宋体");
        //设置字体大小
        headFont.setFontHeightInPoints((short) 12);

        //设置头部字体
        CellStyle headCellStyle = excelWriter.getHeadCellStyle();
        headCellStyle.setFont(headFont);
        //填充背景颜色 否则是灰色
        headCellStyle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.WHITE.getIndex());
        //设置列宽
        excelWriter.setColumnWidth(1, 30);
        excelWriter.setColumnWidth(2, 15);
        excelWriter.setColumnWidth(3, 30);
        excelWriter.setColumnWidth(4, 15);
        excelWriter.setColumnWidth(5, 15);
        excelWriter.setColumnWidth(6, 15);
        excelWriter.setColumnWidth(7, 15);
        excelWriter.setColumnWidth(8, 15);
        excelWriter.setColumnWidth(9, 15);
        excelWriter.setColumnWidth(10, 15);
        excelWriter.setColumnWidth(11, 15);

        //设置普通行的样式
        CellStyle cellStyle = excelWriter.getCellStyle();
        //允许自动换行
        cellStyle.setWrapText(true);
    }

    /**
     * 创建专家组
     *
     * @param title                 excel大标题
     * @param reviewResultExportVOS
     * @param titles                所有的标题
     * @param expertIndex           专家所在索引
     * @return
     */
    private ExcelWriter writeExpertGroup(String title, List<ReviewResultExportVO> reviewResultExportVOS, List<String> titles, int expertIndex, ExpertExcel8ReviewRowStrategy expertExcel8ReviewRowStrategy) {
        ExcelWriter excelWriter = ExcelUtil.getWriter();
        //设置统一的excel样式
        setExcelStyle(excelWriter);
        //获取最后一次merge的次数
        int headMergeSize = 11;
        //跳过当前行  主要是用于最后写入大标题使用
        excelWriter.passCurrentRow();
        //创建专家分组的样式
        CellStyle expertGroupTitleCellStyle = excelWriter.createCellStyle();
        expertGroupTitleCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        expertGroupTitleCellStyle.setAlignment(HorizontalAlignment.CENTER);
        Font headFont = excelWriter.createFont();
        headFont.setBold(true);
        headFont.setFontName("宋体");
        //设置字体大小
        headFont.setFontHeightInPoints((short) 20);
        expertGroupTitleCellStyle.setFont(headFont);

        for (int reviewResultIndex = 0; reviewResultIndex < reviewResultExportVOS.size(); reviewResultIndex++) {
            ReviewResultExportVO reviewResultExportVO = reviewResultExportVOS.get(reviewResultIndex);
            //获取所有分组
            LinkedList<ExpertGroupVO> expertGrops = reviewResultExportVO.getExpertGrops();
            //循环每一组专家
            for (int expertGropsIndex = 0; expertGropsIndex < expertGrops.size(); expertGropsIndex++) {
                //获得专家数量进行合并单元格
                ExpertGroupVO expertGroupVO = expertGrops.get(expertGropsIndex);
                //获取所有的专家
                LinkedList<ExpertVO> experts = expertGroupVO.getExperts();
                int expertSize = experts.size();
                if (expertGropsIndex == 0) {
                    headMergeSize = titles.size() + expertSize - 2;
                    //可以写标题  课题的标题
                    expertExcel8ReviewRowStrategy.writeTopicHead(excelWriter, headMergeSize, reviewResultExportVO);
                }
                //如果分组大于0  方可进行插入二级标题
                if (expertGrops.size() > 0) {
                    //写专家分组的二级标题
                    expertExcel8ReviewRowStrategy.writeExpertGroupTitle(excelWriter, reviewResultExportVO, expertGroupVO, expertGropsIndex, headMergeSize, expertGroupTitleCellStyle);
                }
                //写标题
                writeHead(excelWriter, experts, titles, expertIndex);
                //设置普通样式
                setCellStyle(excelWriter);
                //写入申请课题喽,此处要求自定义啦！
                expertExcel8ReviewRowStrategy.writeDeclTopic(excelWriter, expertGroupVO.getDeclTopics(), reviewResultIndex, expertSize);
            }
        }
        //添加excel的第一大标题
        expertExcel8ReviewRowStrategy.writeExcleTile(excelWriter, headMergeSize, title);
        return excelWriter;
    }


    private void setCellStyle(ExcelWriter excelWriter) {
        CellStyle cellStyle = excelWriter.getCellStyle();
        Font font = excelWriter.createFont();
        font.setFontName("宋体");
        font.setBold(false);
        font.setFontHeightInPoints((short) 12);
        cellStyle.setFont(font);
    }

    /**
     * 写标题
     *
     * @param writer
     * @param experts     专家们
     * @param titleNames  标题们
     * @param expertIndex 专家在哪一列 0 开始
     */
    private void writeHead(ExcelWriter writer, LinkedList<ExpertVO> experts, List<String> titleNames, int expertIndex) {

        int currentRow = writer.getCurrentRow();
        //设置所有的标题
        for (int i = 0; i < titleNames.size(); i++) {
            String title = titleNames.get(i);
            //如果下标大于专家下标
            if (i > expertIndex) {
                writer.merge(currentRow, currentRow + 1, i + experts.size() - 1, i + experts.size() - 1, title, true);
            } //如果当前index是专家的列
            else if (i == expertIndex) {
                //此处值合并一行
                if (i + experts.size() - 1 == i) {
                    writer.writeCellValue(i, currentRow, title);
                } else {
                    writer.merge(currentRow, currentRow, i, i + experts.size() - 1, title, true);
                }

            }//如果当前index是专家的列
            else {
                writer.merge(currentRow, currentRow + 1, i, i, title, true);
            }
        }
        //写入专家名字
        for (int i = 0; i < experts.size(); i++) {
            ExpertVO expertVO = experts.get(i);
            writer.writeCellValue(expertIndex + i, currentRow + 1, expertVO.getExpertName());
        }
        //设置列宽
        writer.setRowHeight(writer.getCurrentRow(), 30);
        writer.setRowHeight(writer.getCurrentRow() + 1, 30);
        writer.setCurrentRow(currentRow + 2);
    }


}
